<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" >

<title>FineUICore扩展（三） | 没想好的个人博客</title>

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

<!-- <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous"> -->
   <!-- Font Awesome CSS-->
   <link href="https://cdn.bootcss.com/font-awesome/5.13.0/css/all.css" rel="stylesheet">

   <link rel="stylesheet" href="https://cdn.bootcss.com/font-awesome/5.7.2/css/all.min.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">

<link rel="shortcut icon" href="https://shixixiyue.gitee.io//favicon.ico?v=1709791195950">
<link rel="stylesheet" href="https://shixixiyue.gitee.io//styles/main.css">



<link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />
<script src="https://jsd.onmicrosoft.cn/npm/vue/dist/vue.js"></script>


<style>
  .hljs-ln{
    padding-bottom: 1.2rem;
    margin: 0rem !important;
  }
  .hljs-ln td {
    border: none !important;
    padding: 2px 6px !important;
    line-height: 1.2rem;
    font-size: 1rem;
  }
  .hljs-ln tr td:first-child  {
    color: cadetblue;
    border-right: 1px solid !important;
  }
  .hljs-ln tr {
    border: none !important;
  }
</style>

    <meta name="description" content="之前为F.Grid做了扩展，自动生成了三个按钮，并和本身的window控件联动弹出编辑窗口。编辑窗口以F.Form为主，这次我把F.Form控件增加扩展，主要用于绑定数据，拿取数据，自动验证并提交，以及简单的布局。








导言
1..." />
    <meta name="keywords" content="FineUICore" />
  </head>
  <body>
    <div id="app" class="main">

      <div class="sidebar" :class="{ 'full-height': menuVisible }">
  <div class="top-container" data-aos="fade-right">
    <div class="top-header-container">
      <a class="site-title-container" href="https://shixixiyue.gitee.io/">
        <img src="https://shixixiyue.gitee.io//images/avatar.png?v=1709791195950" class="site-logo">
        <h1 class="site-title">没想好的个人博客</h1>
      </a>
      <div class="menu-btn" @click="menuVisible = !menuVisible">
        <div class="line"></div>
      </div>
    </div>
    <div>
      
        
          <a href="https://shixixiyue.gitee.io/" class="site-nav">
            首页
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/4gOKry8Qv/" class="site-nav">
            .Net Core
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/njETBpqXu/" class="site-nav">
            FineUICore
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/XyXyeLOBB" class="site-nav">
            读书笔记
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/TyVX6hfCJ" class="site-nav">
            Vue笔记
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/3Hz2sPtzO/" class="site-nav">
            产品
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/Db1wShB_E" class="site-nav">
            其他
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io/" class="site-nav">
            一一一一一一一一一
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//archives" class="site-nav">
            文章归档
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tags" class="site-nav">
            全部标签
          </a>
        
      
    </div>
  </div>
  <div class="bottom-container" data-aos="flip-up" data-aos-offset="0">
    <div class="social-container">
      
        
      
        
      
        
      
        
      
        
      
    </div>
    <div class="site-description">
      没事啥都说
    </div>
    <div class="site-footer">
      QQ：<a href="tencent://message/?uin=935732994&Site=''&Menu=yes">935732994<a/> <a href="http://beian.miit.gov.cn">京ICP备2024045283号<a/> | <a class="rss" href="https://shixixiyue.gitee.io//atom.xml" target="_blank">RSS</a>
    </div>
  </div>
</div>


      <div class="main-container">
        <div class="content-container" data-aos="fade-up">
          <div class="post-detail">
            <h2 class="post-title">FineUICore扩展（三）</h2>
            <div class="post-date">2019-04-01
            
                
                  <a href="https://shixixiyue.gitee.io/tag/njETBpqXu/" class="tag">
                    FineUICore
                  </a>
                
            </div>
            
            <div class="post-content" v-pre>
              <p>之前为F.Grid做了扩展，自动生成了三个按钮，并和本身的window控件联动弹出编辑窗口。编辑窗口以F.Form为主，这次我把F.Form控件增加扩展，主要用于绑定数据，拿取数据，自动验证并提交，以及简单的布局。</p>
<!-- more -->
<p><ul class="markdownIt-TOC">
<li>
<ul>
<li>
<ul>
<li>
<ul>
<li><a href="#%E5%AF%BC%E8%A8%80">导言</a></li>
<li><a href="#1-%E4%B8%BAfform%E7%BB%91%E5%AE%9A%E6%95%B0%E6%8D%AE%E5%AD%97%E6%AE%B5%E8%B5%8B%E5%80%BC">1. 为F.Form绑定数据（字段赋值）</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</p>
<blockquote>
<h4 id="导言">导言</h4>
<p>之前为F.Grid做了扩展，自动生成了三个按钮，并和本身的window控件联动弹出编辑窗口。编辑窗口以F.Form为主，这次我把F.Form控件增加扩展，主要用于绑定数据，拿取数据，自动验证并提交，以及简单的布局。</p>
</blockquote>
<h4 id="1-为fform绑定数据字段赋值">1. 为F.Form绑定数据（字段赋值）</h4>
<p>FineUICore本身有<a href="http://core.fineui.com/#/DataModel/UICompare">model和表单的对照demo</a>，就是MVC的传统写法，通过用模型绑定控件，但是我项目里的Model是没有特性的，就是传统的类</p>
<pre><code>    /// &lt;summary&gt;
    /// ID
    /// &lt;/summary&gt;
    public int Id { get; set; }
</code></pre>
<p>所以如果为表单控件赋值就要写成 ID.Text = ms.XXX;，如果能实现自动匹配映射是很减少工作量的。</p>
<p>首先要在js为F.Form扩展 setValue 和 getValue 方法，将Model的Json格式绑定到表单的各个控件，然后在取值返回Json格式，传到后台(.cs)再转为Model进行保存操作。</p>
<p>这种模式绑定和读取数据很像Grid的操作，Grid中有两个关键属性，DataIDField 和 DataField 属性，一个是标识字段名，一个是绑定的字段名，如果我为F.Form()(.cshtml)扩展这两个属性</p>
<pre><code>    F.Form().Width(900).LabelWidth(100).BodyPadding(5).EnableCollapse(true)
     .ID(&quot;Form1&quot;).Title(&quot;表单1&quot;)
     .DataIDField(&quot;Id&quot;)//数据标识字段名
</code></pre>
<p>表单项</p>
<pre><code>    F.TextBox().Label(&quot;姓名&quot;).DataField(&quot;Name&quot;)//字段名称
    F.DropDownList().Label(&quot;性别&quot;).DataField(&quot;Gender&quot;)//字段名称
</code></pre>
<p>那么js怎么获取到我绑定的 Id，Name，Gender 呢，这里用到了F自带的为HTML标签扩展的属性 Attribute ，该属性在 ControlBaseExtension 下，所有控件继承，该方法直接为HTML标签生成一个属性，js通过 attr 很容易就拿到了，把这个属性拿到，然后直接和JSON匹配就行了。</p>
<p>点击F.Form()，按F12，</p>
<pre><code>    //
    // 摘要:
    //     表单面板控件扩展
    public FormExtension Form();
</code></pre>
<p>FineUIEx类中扩展增加方法  DataIDField</p>
<pre><code>    /// &lt;summary&gt;
    /// 数据标识字段名
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;f&quot;&gt;控件实例&lt;/param&gt;
    /// &lt;param name=&quot;DataIDField&quot;&gt;主键字段&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public static FormExtension DataIDField(this FormExtension f, string DataIDField)
    {
        //为Form增加属性
        f.Attribute(&quot;DataID&quot;, DataIDField);
        return f;
    }
</code></pre>
<p>字段的DataField，在Form的FormRow.Items中参数为IControlBaseExtension[]</p>
<pre><code>    //
    // 摘要:
    //     子控件集合
    //
    // 参数:
    //   extensions:
    public FormRowExtension Items(params IControlBaseExtension[] extensions);
</code></pre>
<p>如果将DataField扩展到IControlBaseExtension中，会有问题，所有控件都继承IControlBaseExtension，但是我只需要输入的控件 比如 TextBox 或 DropDownList ，又不能每个控件都单独扩展，所以找到所有文本输入控件都继承的类 FieldExtension</p>
<pre><code>//
// 摘要:
//     表单字段基类扩展
//
// 类型参数:
//   T:
//
//   TExtension:
public abstract class FieldExtension
</code></pre>
<p>这里还要注意，DataField 方法返回的是当前实例，即谁继承FieldExtension就返回谁（比如F.DropDownList()有DataSource方法而F.TextBox()没有，如果返回统一类型将无法继承该控件实例的单独属性）。</p>
<p>FineUICore自己就解决了这个问题，比如 Label 方法，就在FieldExtension下，所有表单控件继承，</p>
<pre><code>    //
    // 摘要:
    //     标签文本
    //
    // 参数:
    //   param:
    public TExtension Label(string param);
</code></pre>
<p>注意该方法的返回类型是TExtension，泛型，哪来的呢，上层传过来的，比如 DropDownList控件，</p>
<pre><code>//
// 摘要:
//     下拉列表控件扩展
public class DropDownListExtension : TextFieldExtension&lt;DropDownList, DropDownListExtension&gt;
</code></pre>
<p>看&lt;DropDownList, DropDownListExtension&gt;，他已经把自己的类型，通过T参数传到他的继承类中了，所以Label后还可以返回当前实例，落在表单的DataField中，应该这么写</p>
<pre><code>    /// &lt;summary&gt;
    /// 绑定数据字段
    /// &lt;/summary&gt;
    /// &lt;typeparam name=&quot;T&quot;&gt;&lt;/typeparam&gt;
    /// &lt;typeparam name=&quot;TExtension&quot;&gt;&lt;/typeparam&gt;
    /// &lt;param name=&quot;f&quot;&gt;&lt;/param&gt;
    /// &lt;param name=&quot;datafield&quot;&gt;&lt;/param&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    public static TExtension DataField&lt;T, TExtension&gt;(this FieldExtension&lt;T, TExtension&gt; f,string datafield) 
        where T : Field
        where TExtension : FieldExtension&lt;T, TExtension&gt;
    {
        f.Attribute(&quot;data&quot;, datafield);
        return (TExtension)f;
    }
</code></pre>
<p>到此对.cshtml的扩展就结束了，下面是js的扩展，主要是用attr方法，查找 DataID 和 data 属性</p>
<pre><code>if (F.Form) {
    $.extend(F.Form.prototype, {
        //得到数据 （是否验证）
        getdata: function (isv) {
            var t = this;
            var data = t.initData || {};
            if (isv) {
                if (!F.validateForm(t.id, '_self', false, false)) {
                    return false;
                }
            }
            var datael = $(t.el).find(&quot;.f-field[data]&quot;);
            //循环表单项
            $.each(datael, function (i, v) {
                var id = $(v).attr(&quot;id&quot;);
                var d = $(v).attr(&quot;data&quot;).replace(&quot;Data_&quot;, &quot;&quot;);
                //如果存在data属性 
                if (d) {
                    //取值
                    data[d] = F.ui[id].getValue();
                    //注意日期控件 取text，否则会提取出时间戳
                    if (F.ui[id].type == 'datepicker') {
                        data[d] = F.ui[id].getText();
                    }
                }
            })
            //返回json
            return data;
        },
        //设置数据
        setdata: function (data) {
            var t = this;
            t.initData = data;
            var datael = $(t.el).find(&quot;.f-field[data]&quot;);
            //绑定dataid
            var dataid = $(t.el).attr(&quot;DataID&quot;);
            if (dataid &amp;&amp; dataid != '') {
                F.ui[t.id].beforDataID = F.ui[t.id].DataID;
                F.ui[t.id].DataID = data[dataid];
            };
            //循环表单项
            $.each(datael, function (i, v) {
                var id = $(v).attr(&quot;id&quot;);
                var d = $(v).attr(&quot;data&quot;).replace(&quot;Data_&quot;, &quot;&quot;);
                if (d &amp;&amp; (typeof data[d]) != 'undefined') {
                    //找到data属性，并赋值
                    F.ui[id].setValue(data[d]);
                }
            })
        }
    });
}
</code></pre>
<p>扩展完成，使用时可以直接这样</p>
<p>表单控件(.cshtml)</p>
<pre><code>    F.Form().Width(900).LabelWidth(100).BodyPadding(5).EnableCollapse(true)
     .ID(&quot;Form1&quot;).Title(&quot;表单1&quot;)
     .DataIDField(&quot;Id&quot;)
</code></pre>
<p>表单项(.cshtml)</p>
<pre><code>    F.TextBox().Label(&quot;姓名&quot;).DataField(&quot;Name&quot;).Requ(true),
    F.DropDownList().Label(&quot;性别&quot;).DataField(&quot;Gend.Required(true)
     .Items(
        F.ListItem().Text(&quot;男&quot;).Value(&quot;1&quot;),
        F.ListItem().Text(&quot;女&quot;).Value(&quot;0&quot;)
        ),
    F.TextBox().Label(&quot;入学年份&quot;).DataField(&quot;EntranceYear&quot;),
    F.DropDownList().Label(&quot;是否在校&quot;).DataField(&quot;AtSchool&quot;)
     .Items(
        F.ListItem().Text(&quot;是&quot;).Value(&quot;1&quot;),
        F.ListItem().Text(&quot;否&quot;).Value(&quot;0&quot;)
        ),
    F.TextBox().Label(&quot;所学专业&quot;).DataField(&quot;Major&quot;),
    F.TextBox().Label(&quot;分组&quot;).DataField(&quot;Group&quot;)
</code></pre>
<p>js(.cshtml)</p>
<pre><code>    F.ready(function () {
        F.ui['Form1'].setdata(@Html.Raw(ViewBag.data));
    })
</code></pre>
<p>后台.cs</p>
<pre><code>    public ActionResult Index()
    {
        MsStudent ms1 = new MsStudent();
        //得到实体数据
        ms1 = studentHelper.GetMsById(Convert.ToInt32(101));
        ViewBag.data = JObject.FromObject(ms1).ToString();
        return View();
    }
</code></pre>
<blockquote>
<p>具体效果，可以在<a href="http://140.143.155.224:8086/#/Form/FormData">FineUIMVC扩展</a>中查看。</p>
</blockquote>

            </div>
            
              <div class="tag-container">
                
                  <a href="https://shixixiyue.gitee.io/tag/njETBpqXu/" class="tag">
                    FineUICore
                  </a>
                
              </div>
            
            
              <div class="next-post">
                <div class="next">下一篇</div>
                <a href="https://shixixiyue.gitee.io/2019032801/">
                  <h3 class="post-title">
                    FineUICore扩展（二）
                  </h3>
                </a>
              </div>
            

            

          </div>

        </div>
      </div>
    </div>

    <script src="https://unpkg.com/aos@next/dist/aos.js"></script>
<script type="application/javascript">

AOS.init();

var app = new Vue({
  el: '#app',
  data: {
    menuVisible: false,
  },
})

</script>


  <script src="//jsd.onmicrosoft.cn/gh/highlightjs/cdn-release@11.5.1/build/highlight.min.js"></script>
  <script>
    hljs.initHighlightingOnLoad();
    //hljs.registerLanguage('mermaid', window.hljsDefineMermaid);
  </script>
  <script src="//jsd.onmicrosoft.cn/npm/highlightjs-line-numbers.js@2.8.0/dist/highlightjs-line-numbers.min.js"></script>
  <script>
    hljs.initLineNumbersOnLoad({
      singleLine: true
    });
  </script>
 <script src="https://jsd.onmicrosoft.cn/npm/mermaid/dist/mermaid.min.js"></script>
   <script>
    mermaid.initialize({
      startOnLoad: true,
      securityLevel: 'loose',
    });
  </script>





  </body>
</html>
